﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mongaba.Core.Listeners;
using Mongaba.Core.ServiceContracts;
using System.ServiceModel;
using Mongaba.Core.DataContracts;
using Mongaba.Core.Registers;

namespace Mongaba.Core.Factory
{
    internal  class ProcessFactory
    {
        static ServiceHost svcHost;

        public static IMongabaProcess GetLocalInstance()
        {
            if (svcHost != null)
            {
                return (IMongabaProcess)svcHost.SingletonInstance;
            }
            else
            {
                return null;
            }
        }
        public static void RemoveRemoteInstanceConnection(string address)
        {
            try
            {
                if (remoteProcessInstances.ContainsKey(address))
                {
                    (remoteProcessInstances[address] as IClientChannel).Close();
                    remoteProcessChannelFactoryInstances[address].Close();
                }
            }            
            finally
            {
                remoteProcessInstances.Remove(address);
                remoteProcessChannelFactoryInstances.Remove(address);
            }
        }
        static Dictionary<string, IMongabaProcess> remoteProcessInstances = new Dictionary<string, IMongabaProcess>();
        static Dictionary<string, ChannelFactory<IMongabaProcess>> remoteProcessChannelFactoryInstances = new Dictionary<string, ChannelFactory<IMongabaProcess>>();


        public static IMongabaProcess GetRemoteInstance(string address)
        {
            if (remoteProcessInstances.ContainsKey(address))
            {
                RemoveRemoteInstanceConnection(address);
            }
            ChannelFactory<IMongabaProcess> factory = new ChannelFactory<IMongabaProcess>(BindingCreator.CreateNewTcpBinding(address.Replace(".", "")), Utilities.generateProcessEndPointAddress(address));
            IMongabaProcess proxy = factory.CreateChannel();
            remoteProcessInstances.Add(address, proxy);
            remoteProcessChannelFactoryInstances.Add(address, factory);

            return proxy;         
        }

        public static void StartLocalInstance(GroupContract group, UserContract user)
        {
            if (svcHost == null)
            {
                MongabaProcess mp = new MongabaProcess(user,group);
                svcHost = new ServiceHost(mp, Utilities.generateProcessEndPointAddress(Utilities.HostIp.ToString()).Uri);
                svcHost.Description.Endpoints.Clear();
                BindingCreator.CreateProcessBinding();
                svcHost.OpenTimeout = TimeSpan.FromDays(2);
                svcHost.CloseTimeout = TimeSpan.FromDays(2);
                svcHost.AddServiceEndpoint(typeof(IMongabaProcess), BindingCreator.GetProcessBinding(), "");
                svcHost.Open();
                Console.WriteLine("A instância do processo local foi iniciada.");
            }
            else
            {
                StopLocalInstance();
                StartLocalInstance(group, user);

            }
        }

        public static bool IsStarted
        {
            get { return svcHost != null; }
        }

        public static void StopLocalInstance()
        {
            if (svcHost != null)
            {
                svcHost.Close(TimeSpan.FromSeconds(1));
                svcHost = null;
            }

            Console.WriteLine("A instância do processo local foi finalizada.");
        }

    }
}
